<?php
/*
 * description：
 * author：wh
 * email：
 * createTime：{2021/3/22} {9:42} 
 */

namespace wanghua\general_utility_tools_php\ftp;


/**
 * 利用ftp操作服务器文件（增删改查下载）
 * Class Ftp
 * @package wanghua\general_utility_tools_php\ftp
 */
class Ftp
{
    public $off; // 返回操作状态(成功/失败)
    public $conn_id; // FTP连接

    /**
     * FTP连接
     * $host -- FTP主机
     * $port -- 端口
     * $user -- 用户名
     * $password -- 密码
     */
    function __construct(string $host,string $port='21',string $user,string $password)
    {
        set_time_limit(10);//防止连接超时

        $this->conn_id = ftp_connect($host, $port);
        if(!$this->conn_id) throw new \Exception("FTP服务器连接失败");
        $login_res = ftp_login($this->conn_id, $user, $password);
        if(!$login_res) throw new \Exception("FTP服务器登陆失败");
        ftp_pasv($this->conn_id, false); // true打开被动模拟，默认关闭，如果总是失败，可试试true
    }

    /**
     * desc：打开被动模拟，登录后使用
     * author：wh
     */
    function set_ftp_pasv(){
        ftp_pasv($this->conn_id, true); // true打开被动模拟
    }

    /**
     * 上传文件
     * param $path 本地文件路径[包含文件名]
     * param $newPath 目标目录[包含文件名][默认存放在ftp用户被授权的根路径]
     * param bool $type 若目标目录不存在则新建
     */
    function up_file($path, $newPath, $type = true)
    {
        if ($type) $this->dir_mkdirs($newPath);
        $this->off = ftp_put($this->conn_id, $newPath, $path, FTP_BINARY);
        if (!$this->off)
            return ['code'=>500, 'msg'=>'文件上传失败，请检查权限及路径是否正确！'];
        return ['code'=>200, 'msg'=>'文件移动成功'];
    }

    /**
     * 移动文件
     * 特别注意：
     * $path 如果是当前目录，则必须以 “/”开始
     * 正确：/test2.zip
     * 错误：test2.zip
     * param $path 原路径(含文件名)
     * param $newPath 新路径(含文件名)
     * param bool $type 若目标目录不存在则新建
     */
    function move_file($path, $newPath, $ftpbasedir, $type = true)
    {
        if ($type) $this->ftp_mksubdirs($ftpbasedir,$newPath);
        $this->off = ftp_rename($this->conn_id, $path, $newPath);
        if (!$this->off)
            return ['code'=>500, 'msg'=>'文件移动失败，请检查权限及原路径是否正确！'];
        return ['code'=>200, 'msg'=>'文件移动成功'];
    }

    /**
     * 文件改名
     * param $path 原路径
     * param $newPath 新路径
     */
    function rename_file($path, $newPath)
    {
        $this->off = ftp_rename($this->conn_id, $path, $newPath);
        if (!$this->off)
            return ['code'=>500, 'msg'=>'文件改名失败，请检查权限及原路径是否正确！'];
        return ['code'=>200, 'msg'=>'文件改名成功'];
    }

    /**
     * 复制文件
     * 说明：由于FTP无复制命令,本方法变通操作为：下载后再上传到新的路径
     * param $path 原路径
     * param $newPath 新路径
     * param bool $type 若目标目录不存在则新建
     */
    function copy_file($path, $newPath, $type = true)
    {
        $downPath = "c:/tmp.dat";
        $this->off = ftp_get($this->conn_id, $downPath, $path, FTP_BINARY);// 下载
        if (!$this->off)
            return ['code'=>500, 'msg'=>'文件复制失败，请检查权限及原路径是否正确！'];

        $this->up_file($downPath, $newPath, $type);
        return ['code'=>200, 'msg'=>'文件复制成功'];
    }

    /**
     * 删除文件
     * param $path 路径
     */
    function del_file($path)
    {
        $this->off = ftp_delete($this->conn_id, $path);
        if (!$this->off)
            return ['code'=>500, 'msg'=>'文件删除失败，请检查权限及路径是否正确！'];

        return ['code'=>200, 'msg'=>'文件删除成功'];
    }

    /**
     * desc：删除给定目录
     * 注：
     * 删除多个目录需重复调用
     * author：wh
     * param $dir
     * return bool
     */
    function del_dir($dir){


        $children = ftp_nlist ($this->conn_id, $dir);
        if(!$children) {
            ftp_rmdir($this->conn_id, $dir);

            return true;
        }

        throw new \Exception('请确保目录中无内容');

    }


    /**
     * desc：生成目录
     * author：wh
     * param $ftpcon
     * param $ftpbasedir
     * param $ftpath
     */
    function ftp_mksubdirs($ftpbasedir,$ftpath){
        ftp_chdir($this->conn_id, $ftpbasedir); // /var/www/uploads
        $parts = explode('/',$ftpath); // 2013/06/11/username

        if(strpos($parts[count($parts)-1], '.')){
            unset($parts[count($parts)-1]);
        }

        foreach($parts as $part){
            if(!ftp_chdir($this->conn_id, $part)){
                ftp_mkdir($this->conn_id, $part);
                ftp_chdir($this->conn_id, $part);
                //ftp_chmod($this->conn_id, 0777, $part);
            }
        }
    }

    /**
     * desc：使用ftp连接方式下载文件
     * author：wh
     * param string $local_file 文件本地的路径（如果文件已经存在，则会被覆盖）。
     * param string $remote_file 文件的远程路径。[默认查找ftp用户被授权的根路径]
     * return array
     */
    function download(string $local_file, string $remote_file){
        // 进行ftp下载[默认保存在本地根目录]
        if (!ftp_get($this->conn_id, $local_file, $remote_file, FTP_BINARY)) {
            return ['code'=>500, 'msg'=>'ftp download fail'];
        }
        return ['code'=>200, 'msg'=>'ftp download success'];
    }

    /**
     * desc：判断ftp文件大小, 如果>-1, 说明文件存在;否则不存在.
     * author：wh
     * param $remote_file
     * return int
     */
    function ftp_size($remote_file){
        return ftp_size($this->conn_id, $remote_file);
    }

    /**
     * desc：返回当前目录
     * author：wh
     * return false|string
     */
    function ftp_pwd(){
        return ftp_pwd($this->conn_id);
    }
    /**
     * 关闭FTP连接
     */
    function close()
    {
        ftp_close($this->conn_id);
    }
}